#ifndef DEF_H
#define DEF_H

#include <assert.h>
#include <errno.h>
#include <getopt.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#include <SDL2/SDL_image.h>

#define DEBUG 0

#define WINDOW_TITLE "cmus-remote-graphical-sdl-c"
#define DEFAULT_WINDOW_W 300
#define DEFAULT_WINDOW_H 300

#define DEFAULT_FONT_SIZE 20
#define FONTHEIGHT ((int) ((float)FONTSIZE * 1.5))

#define WHITE 0xffffffff
#define BLACK 0x000000ff

#define BG 0x100410ff
#define FG 0xff87ffff

/* groups a rect with a texture */
typedef struct {
    SDL_Texture *texture;
    SDL_Rect rect;
} cr_drawable;

typedef struct {
    char id;
    unsigned int x;
    unsigned int y;
    unsigned int w;
    unsigned int h;
    void (*callback)(void* data);
    /* buttons often have double textures associated with them */
    /* so simply storing two of them is a pragmatic approach */
    cr_drawable visual[2];
} button;

/* using a simple linked list for buttons */
typedef struct button_node {
    button payload;
    struct button_node *next;
} cr_button_node;

typedef struct {
    uint64_t duration;
    char *file;
    char *album_tag;
    char *albumartist_tag;
    char *artist_tag;
    char *comment_tag;
    char *date_tag;
    char *genre_tag;
    char *title_tag;
    char *stream;
    uint64_t discnumber_tag;
    uint64_t cr_tracknumber_tag;
} cr_track;

typedef struct {
    char *aaa_mode;
    char *status;
    uint64_t vol_left;
    uint64_t vol_right;
    uint64_t position;
    bool repeat;
    bool repeat_current;
    bool shuffle;
} cr_player;

enum {
    BUTTON_TOGGLE_STATUS, BUTTON_NEXT, BUTTON_PREV, BUTTON_TOGGLE_AAA_MODE
};

/* stores indices for various fields that can cause events */
/* to happen, used to encode udpate information */
typedef enum {
    TOKEN_DURATION = 0, TOKEN_FILE, TOKEN_ALBUM_TAG, TOKEN_ALBUMARTIST_TAG,
    TOKEN_ARTIST_TAG, TOKEN_COMMENT_TAG, TOKEN_DATE_TAG, TOKEN_GENRE_TAG,
    TOKEN_TITLE_TAG, TOKEN_STREAM, TOKEN_DISCNUMBER_TAG, TOKEN_TRACKNUMBER_TAG,
    TOKEN_AAA_MODE, TOKEN_STATUS, TOKEN_VOL_LEFT, TOKEN_VOL_RIGHT,
    TOKEN_POSITION, TOKEN_REPEAT, TOKEN_REPEAT_CURRENT, TOKEN_SHUFFLE,
    /* delimits all the tokens for iteration */
    TOKEN_ENUM_SIZE
} token;

/* stores miscellaneous state information */
typedef struct {
    /* commands dynamic renderer updates */
    bool render_change;
    /* stores whether last parse token was completely parsed */
    bool incomplete_parse;

    /* stores last frame */
    int frame;
    /* stores active screen width */
    int window_w;
    /* stores active screen height */
    int window_h;
    /* stores font height */
    int font_height;
    /* stores border to all sides */
    int border;

    /* cmus state hash */
    uint64_t previous_info_hash;

    /* points to the active window */
    SDL_Window *window;
    /* points to the active renderer */
    SDL_Renderer *renderer;
    /* points to the active display */
    SDL_Texture *display;
    /* points to the active ttf_font */
    TTF_Font *font;

    /* points to the root node of the button linked list*/
    cr_button_node *root;
    /* points to the tail node of the button linked list*/
    cr_button_node *tail;

    /* stores the current cr_track */
    cr_track *track;
    /* stores the current cr_player */
    cr_player *player;

    /* stores update information */
    bool update[TOKEN_ENUM_SIZE];
    /* stores all drawable important for updates */
    cr_drawable drawables[TOKEN_ENUM_SIZE];
    /* stores secondary layer of drawables */
    /* in case more layers are needed, it can be considered to define a more */
    /* generic structure for drawables */
    cr_drawable drawextras[TOKEN_ENUM_SIZE];
} cr_state;

#endif